package com.zhouyu;

import com.zhouyu.service.OrderService;
import com.zhouyu.service.StringToUserPropertyEditor;
import com.zhouyu.service.User;
import com.zhouyu.service.UserServiceNew;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.io.Resource;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.ClassMetadata;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.SimpleMetadataReaderFactory;

import java.util.Locale;
import java.util.Map;

// 我的微信：dadudu6789
// 我的公众号：IT周瑜

public class Test {

	Log log = LogFactory.getLog(Test.class);


	public static void main(String[] args) {
		Test test = new Test();
		test.testMetadataReaderFactory();

		// 创建一个Spring容器
		/*AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
		UserServiceNew userServiceNew = (UserServiceNew) applicationContext.getBean("userServiceNew");
		userServiceNew.transA();*/

		/**
		 * 手动注册一个 beanDefinition ，Spring 会自动创建一个 Bean
		 */
		/*AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
		beanDefinition.setBeanClass(UserServiceNew.class);
		beanDefinition.setScope("singleton");
		beanDefinition.setLazyInit(true);
		beanDefinition.setInitMethodName("initMethod");
		applicationContext.registerBeanDefinition("userServiceNew", beanDefinition);*/

		/*AnnotatedBeanDefinitionReader abdr = new AnnotatedBeanDefinitionReader(applicationContext);
		// 将 User.class 解析为BeanDefinition
		abdr.register(User.class);
		System.out.println(applicationContext.getBean("user"));
		System.out.println(applicationContext.getBean("user"));
*/

//		UserService userService1 = new UserService();
//
//		for (Field field : userService1.getClass().getDeclaredFields()) {
//			if (field.isAnnotationPresent(Autowired.class)) {
//				field.set(userService1, ??);
//			}
//		}
//
//
//		for (Method method : userService1.getClass().getDeclaredMethods()) {
//			if (method.isAnnotationPresent(PostConstruct.class)) {
//				method.invoke(userService1, null);
//			}
//		}
//
//		if (userService1 instanceof InitializingBean) {
//			try {
//				((InitializingBean)userService1).afterPropertiesSet();
//			} catch (Exception e) {
//				e.printStackTrace();
//			}
//		}
//
//		ProxyFactory proxyFactory = new ProxyFactory();
//		proxyFactory.setTarget(userService1);
//		proxyFactory.addAdvice(new MethodInterceptor() {
//			@Nullable
//			@Override
//			public Object invoke(@NotNull MethodInvocation invocation) throws Throwable {
//				System.out.println("切面逻辑 before...");
//				Object result = invocation.proceed();
////				Object result = invocation.getMethod().invoke(invocation.getThis(), invocation.getArguments());
//				System.out.println("切面逻辑 after...");
//				return result;
//			}
//		});
//		UserService userService2  = (UserService) proxyFactory.getProxy();
//		userService2.test();
	}

	/**
	 * 使用 ClassPathXmlApplicationContext 加载 Bean
	 */
	public void testClassPathXmlApplicationContext() {
		// 创建一个Spring容器
		ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring.xml");
		UserServiceNew userServiceNew = (UserServiceNew) applicationContext.getBean("userServiceNew");
		System.out.println(userServiceNew);
		userServiceNew.test();
	}

	/**
	 * 使用 XmlBeanDefinitionReader 加载 Bean
	 */
	public void testXmlBeanDefinitionReader() {
		// 创建一个Spring容器
		AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
		XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(applicationContext);
		int loadBeanDefinitions = reader.loadBeanDefinitions("spring.xml");
		UserServiceNew userServiceNew = (UserServiceNew) applicationContext.getBean("userServiceNew");
		System.out.println(userServiceNew);
		userServiceNew.transA();
	}

	/**
	 * 使用 ClassPathBeanDefinitionScanner 扫描 Bean
	 */
	public void testClassPathBeanDefinitionScanner() {
		// 创建一个Spring容器
		AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
		applicationContext.refresh();
		ClassPathBeanDefinitionScanner reader = new ClassPathBeanDefinitionScanner(applicationContext);
		reader.scan("com.zhouyu.service");
		UserServiceNew userServiceNew = (UserServiceNew) applicationContext.getBean("userServiceNew");
		System.out.println(userServiceNew);
	}

	/**
	 * 使用 DefaultListableBeanFactory 注册 bean
	 */
	public void testDefaultListableBeanFactory() {
		DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
		AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
		beanDefinition.setBeanClass(UserServiceNew.class);
		beanDefinition.setScope("singleton");
		beanDefinition.setLazyInit(true);

		beanFactory.registerBeanDefinition("userServiceNew", beanDefinition);

		System.out.println(beanFactory.getBean("userServiceNew"));
	}

	/**
	 * 国际化测试
	 */
	public void testMessageSource() {
		// 创建一个Spring容器
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
		System.out.println(context.getMessage("name", null, Locale.ENGLISH));
		System.out.println(context.getMessage("test", null, Locale.getDefault()));

	}

	/**
	 * 加载资源
	 */
	public void loadResource() {
		try {
			// 创建一个Spring容器
			AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

			Resource resource = context.getResource("file:/Users/zhangsan/data/wp/idea-180503/spring-framework-5.3.10/tuling/src/main/resources/messages.properties");

			System.out.println("content-length");
			System.out.println(resource.contentLength());

			resource = context.getResource("http://www.baidu.com");
			System.out.println(resource.contentLength());

			resource = context.getResource("classpath:spring.xml");
			System.out.println(resource.contentLength());

			// 批量获取
			Resource[] resources = context.getResources("classpath:com/zhouyu/service/*.class");
			for (Resource tmpRes : resources) {
				System.out.println(tmpRes.contentLength());
				System.out.println(tmpRes.getFilename());
			}
		} catch (Exception e) {
			log.error("error:", e);
		}
	}


	/**
	 * 获取运行时环境信息
	 */
	public void getRunTimeInfo() {
		try {
			// 创建一个Spring容器
			AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
			Map<String, Object> systemEnvironment = context.getEnvironment().getSystemEnvironment();
			System.out.println(systemEnvironment);


			System.out.println("--------------");
			Map<String, Object> systemProperties = context.getEnvironment().getSystemProperties();
			System.out.println(systemProperties);

			System.out.println("--------------");
			MutablePropertySources propertySources = context.getEnvironment().getPropertySources();
			System.out.println(propertySources);

			// 可以利用 @PropertySource("classpath:spring.properties") 来使得某个properties文件中的参数添加到运行时环境中
			System.out.println(context.getEnvironment().getProperty("app.version"));

		} catch (Exception e) {
			log.error("error:", e);
		}
	}


	/**
	 * 获取运行时环境信息
	 */
	public void testPublishEvent() {
		try {
			// 创建一个Spring容器
			AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
			context.publishEvent(new ApplicationEvent("这是个测试事件") {
				@Override
				public String getSource() {
					return super.getSource().toString();
				}

				@Override
				public String toString() {
					return super.toString();
				}
			});
		} catch (Exception e) {
			log.error("error:", e);
		}
	}


	/**
	 * 获取运行时环境信息
	 */
	public void testPropertyEditor() {
		try {
			StringToUserPropertyEditor propertyEditor = new StringToUserPropertyEditor();
			propertyEditor.setAsText("lisi");

			User source = (User) propertyEditor.getValue();
			System.out.println(source);

		} catch (Exception e) {
			log.error("error:", e);
		}
	}


	/**
	 * 获取运行时环境信息
	 */
	public void testSpringPropertyEditor() {
		try {
			// 创建一个Spring容器
			AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
			OrderService bean = context.getBean(OrderService.class);
			System.out.println(bean.getUser());
		} catch (Exception e) {
			log.error("error:", e);
		}
	}

	/**
	 * 测试转换器
	 */
	public void testConversionService() {
		try {
			// 创建一个Spring容器
			AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
			OrderService bean = context.getBean(OrderService.class);
			System.out.println(bean.getUser());
		} catch (Exception e) {
			log.error("error:", e);
		}
	}


	/**
	 * 测试转换器
	 */

	public void testMetadataReaderFactory() {
		try {
			SimpleMetadataReaderFactory simpleMetadataReaderFactory = new SimpleMetadataReaderFactory();

			// 构造一个MetadataReader
			MetadataReader metadataReader = simpleMetadataReaderFactory.getMetadataReader("com.zhouyu.service.OrderService");

			// 得到一个ClassMetadata，并获取了类名
			ClassMetadata classMetadata = metadataReader.getClassMetadata();

			System.out.println(classMetadata.getClassName());

			// 获取一个AnnotationMetadata，并获取类上的注解信息
			AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
			for (String annotationType : annotationMetadata.getAnnotationTypes()) {
				System.out.println(annotationType);
			}
		} catch (Exception e) {
			log.error("error:", e);
		}
	}

}







